#!/usr/bin/env python3
"""
分布式文件同步系统 - TUI管理界面
使用Rich库实现现代化终端用户界面

安装依赖:
pip install rich requests

运行方式:
python tui_monitor.py
"""

import json
import time
import sys
from datetime import datetime
from typing import Dict, Any, Optional

try:
    import requests
    from rich.console import Console
    from rich.panel import Panel
    from rich.table import Table
    from rich.layout import Layout
    from rich.live import Live
    from rich.text import Text
    from rich.progress import Progress, SpinnerColumn, TextColumn
    from rich.align import Align
    from rich.columns import Columns
    from rich import box
except ImportError as e:
    print(f"❌ 缺少依赖库: {e}")
    print("请安装依赖: pip install rich requests")
    sys.exit(1)


class FileSyncTUI:
    """分布式文件同步系统TUI界面"""

    def __init__(self, backend_host: str = "localhost", backend_port: int = 8889):
        self.console = Console()
        self.backend_url = f"http://{backend_host}:{backend_port}"
        self.last_update = None
        self.error_count = 0

        # 缓存数据
        self.cached_data = {
            "status": {},
            "config": {},
            "network": {},
            "files": {},
            "logs": {},
        }

    def fetch_data(self, endpoint: str) -> Optional[Dict[str, Any]]:
        """从后端API获取数据"""
        try:
            response = requests.get(f"{self.backend_url}/api/{endpoint}", timeout=2)
            if response.status_code == 200:
                self.error_count = 0
                return response.json()
            else:
                self.error_count += 1
                return None
        except Exception as e:
            self.error_count += 1
            if self.error_count <= 3:  # 只显示前3次错误
                self.console.print(f"[red]API请求失败: {e}[/red]")
            return None

    def update_cached_data(self):
        """更新缓存数据"""
        endpoints = ["status", "config", "network", "files", "logs"]
        for endpoint in endpoints:
            data = self.fetch_data(endpoint)
            if data:
                self.cached_data[endpoint] = data
        self.last_update = datetime.now()

    def create_header(self) -> Panel:
        """创建页头"""
        status_data = self.cached_data.get("status", {})

        # 系统基本信息
        node_name = status_data.get("nodeName", "Unknown")
        version = status_data.get("version", "1.0.0")
        uptime = status_data.get("uptime", 0)
        uptime_str = self.format_uptime(uptime)

        # 状态指示器
        services = status_data.get("services", {})
        network_status = "🟢 运行中" if services.get("network", False) else "🔴 已停止"
        watcher_status = (
            "🟢 运行中" if services.get("fileWatcher", False) else "🔴 已停止"
        )
        api_status = "🟢 运行中" if services.get("api", False) else "🔴 已停止"

        header_text = f"""
[bold blue]分布式文件同步系统控制台[/bold blue]
节点: {node_name} | 版本: {version} | 运行时间: {uptime_str}
网络服务: {network_status} | 文件监控: {watcher_status} | API服务: {api_status}
        """.strip()

        return Panel(
            Align.center(header_text),
            title="🚀 系统状态",
            border_style="bright_blue",
            box=box.ROUNDED,
        )

    def create_network_panel(self) -> Panel:
        """创建网络状态面板"""
        network_data = self.cached_data.get("network", {})
        status_data = self.cached_data.get("status", {})

        table = Table(box=box.SIMPLE)
        table.add_column("项目", style="cyan", no_wrap=True)
        table.add_column("状态", style="green")

        # 网络信息
        network_info = status_data.get("network", {})
        port = network_info.get("port", "N/A")
        api_port = network_info.get("apiPort", "N/A")
        connections = network_info.get("connections", 0)
        max_connections = network_info.get("maxConnections", 10)

        table.add_row("监听端口", f"{port}")
        table.add_row("API端口", f"{api_port}")
        table.add_row("活动连接", f"{connections}/{max_connections}")

        # 消息队列
        queues = network_data.get("messageQueues", {})
        incoming = queues.get("incoming", 0)
        outgoing = queues.get("outgoing", 0)
        table.add_row("传入队列", f"{incoming} 条消息")
        table.add_row("传出队列", f"{outgoing} 条消息")

        # 连接的节点
        connected_nodes = network_data.get("connectedNodes", [])
        if connected_nodes:
            table.add_row("连接节点", f"{len(connected_nodes)} 个节点")
        else:
            table.add_row("连接节点", "[yellow]无连接[/yellow]")

        return Panel(table, title="🌐 网络状态", border_style="green", box=box.ROUNDED)

    def create_files_panel(self) -> Panel:
        """创建文件监控面板"""
        files_data = self.cached_data.get("files", {})

        table = Table(box=box.SIMPLE)
        table.add_column("项目", style="cyan", no_wrap=True)
        table.add_column("状态", style="green")

        is_running = files_data.get("isRunning", False)
        queue_size = files_data.get("eventQueueSize", 0)
        monitored_paths = files_data.get("monitoredPaths", [])

        status_text = "🟢 运行中" if is_running else "🔴 已停止"
        table.add_row("监控状态", status_text)
        table.add_row("事件队列", f"{queue_size} 个事件")
        table.add_row("监控目录", f"{len(monitored_paths)} 个目录")

        # 显示监控路径
        if monitored_paths:
            for i, path in enumerate(monitored_paths[:3]):  # 最多显示3个
                label = "监控路径" if i == 0 else ""
                table.add_row(label, f"📁 {path}")
            if len(monitored_paths) > 3:
                table.add_row("", f"... 还有 {len(monitored_paths) - 3} 个")

        return Panel(table, title="📁 文件监控", border_style="yellow", box=box.ROUNDED)

    def create_config_panel(self) -> Panel:
        """创建配置信息面板"""
        config_data = self.cached_data.get("config", {})

        table = Table(box=box.SIMPLE)
        table.add_column("配置项", style="cyan", no_wrap=True)
        table.add_column("值", style="green")

        # 网络配置
        network_config = config_data.get("network", {})
        table.add_row("网络端口", str(network_config.get("port", "N/A")))
        table.add_row("最大连接", str(network_config.get("maxConnections", "N/A")))
        table.add_row("心跳间隔", f"{network_config.get('heartbeatInterval', 0)}ms")

        # 同步配置
        sync_config = config_data.get("sync", {})
        auto_enabled = "🟢 启用" if sync_config.get("autoEnabled", False) else "🔴 禁用"
        table.add_row("自动同步", auto_enabled)
        table.add_row("同步间隔", f"{sync_config.get('interval', 0)}ms")
        table.add_row("冲突策略", sync_config.get("conflictStrategy", "N/A"))

        # 日志配置
        log_config = config_data.get("log", {})
        log_enabled = "🟢 启用" if log_config.get("fileEnabled", False) else "🔴 禁用"
        table.add_row("日志文件", log_enabled)
        table.add_row("日志级别", log_config.get("level", "N/A"))

        return Panel(table, title="⚙️ 系统配置", border_style="magenta", box=box.ROUNDED)

    def create_footer(self) -> Panel:
        """创建页脚"""
        current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        update_time = (
            self.last_update.strftime("%H:%M:%S") if self.last_update else "从未"
        )

        # 连接状态
        if self.error_count == 0:
            connection_status = "[green]🟢 连接正常[/green]"
        elif self.error_count < 5:
            connection_status = (
                f"[yellow]🟡 连接不稳定 ({self.error_count} 次错误)[/yellow]"
            )
        else:
            connection_status = "[red]🔴 连接断开[/red]"

        footer_text = f"当前时间: {current_time} | 最后更新: {update_time} | {connection_status} | 按 Ctrl+C 退出"

        return Panel(Align.center(footer_text), border_style="dim", box=box.SIMPLE)

    def create_layout(self) -> Layout:
        """创建主布局"""
        layout = Layout()

        # 主要分割
        layout.split_column(
            Layout(name="header", size=6),
            Layout(name="main"),
            Layout(name="footer", size=3),
        )

        # 主区域分割为2x2网格
        layout["main"].split_row(Layout(name="left"), Layout(name="right"))

        layout["left"].split_column(Layout(name="network"), Layout(name="files"))

        layout["right"].split_column(Layout(name="config"), Layout(name="logs"))

        return layout

    def update_layout(self, layout: Layout):
        """更新布局内容"""
        try:
            layout["header"].update(self.create_header())
            layout["network"].update(self.create_network_panel())
            layout["files"].update(self.create_files_panel())
            layout["config"].update(self.create_config_panel())
            layout["logs"].update(self.create_logs_panel())
            layout["footer"].update(self.create_footer())
        except Exception as e:
            # 如果更新失败，显示错误信息
            error_panel = Panel(
                f"[red]界面更新失败: {e}[/red]", title="错误", border_style="red"
            )
            layout["main"].update(error_panel)

    def create_logs_panel(self) -> Panel:
        """创建日志面板"""
        logs_data = self.cached_data.get("logs", {})
        entries = logs_data.get("entries", [])

        if not entries:
            return Panel(
                Align.center("[dim]暂无日志信息[/dim]"),
                title="📝 系统日志",
                border_style="blue",
                box=box.ROUNDED,
            )

        log_text = Text()
        for entry in entries[-5:]:  # 显示最近5条日志
            timestamp = datetime.fromtimestamp(entry.get("timestamp", 0) / 1000)
            level = entry.get("level", "INFO")
            message = entry.get("message", "")

            # 根据日志级别设置颜色
            if level == "ERROR":
                color = "red"
            elif level == "WARN":
                color = "yellow"
            elif level == "DEBUG":
                color = "dim"
            else:
                color = "white"

            log_text.append(f"{timestamp.strftime('%H:%M:%S')} ", style="dim")
            log_text.append(f"[{level}]", style=color)
            log_text.append(f" {message}\n", style=color)

        return Panel(
            log_text, title="📝 系统日志", border_style="blue", box=box.ROUNDED
        )

    @staticmethod
    def format_uptime(milliseconds: int) -> str:
        """格式化运行时间"""
        if milliseconds <= 0:
            return "未知"

        seconds = milliseconds // 1000
        if seconds < 60:
            return f"{seconds}秒"
        elif seconds < 3600:
            minutes = seconds // 60
            return f"{minutes}分钟"
        elif seconds < 86400:
            hours = seconds // 3600
            minutes = (seconds % 3600) // 60
            return f"{hours}小时{minutes}分钟"
        else:
            days = seconds // 86400
            hours = (seconds % 86400) // 3600
            return f"{days}天{hours}小时"

    def show_startup_screen(self):
        """显示启动画面"""
        startup_text = """
[bold bright_blue]🚀 分布式文件同步系统 TUI 监控器[/bold bright_blue]

[yellow]正在连接后端服务...[/yellow]
        """

        panel = Panel(
            Align.center(startup_text),
            title="启动中",
            border_style="bright_blue",
            box=box.DOUBLE,
        )

        self.console.print(panel)
        time.sleep(1)

    def show_connection_error(self):
        """显示连接错误"""
        error_text = f"""
[bold red]❌ 连接失败[/bold red]

无法连接到后端服务: {self.backend_url}

请确保:
1. Java后端服务正在运行
2. API端口 8889 未被占用
3. 防火墙允许连接

[dim]3秒后重试...[/dim]
        """

        panel = Panel(
            Align.center(error_text),
            title="连接错误",
            border_style="red",
            box=box.DOUBLE,
        )

        self.console.clear()
        self.console.print(panel)
        time.sleep(3)

    def run(self):
        """运行TUI界面"""
        try:
            self.console.clear()
            self.show_startup_screen()

            # 初始测试连接
            initial_data = self.fetch_data("status")
            if not initial_data:
                while True:
                    self.show_connection_error()
                    self.console.clear()
                    initial_data = self.fetch_data("status")
                    if initial_data:
                        break

            self.console.clear()
            layout = self.create_layout()

            with Live(layout, refresh_per_second=2, screen=True):
                while True:
                    try:
                        self.update_cached_data()
                        self.update_layout(layout)
                        time.sleep(1)  # 每秒更新一次
                    except KeyboardInterrupt:
                        break
                    except Exception as e:
                        self.console.print(f"[red]运行时错误: {e}[/red]")
                        time.sleep(1)

        except KeyboardInterrupt:
            pass
        finally:
            self.console.clear()
            self.console.print(
                "[bold green]👋 感谢使用分布式文件同步系统 TUI 监控器！[/bold green]"
            )


def main():
    """主函数"""
    # 解析命令行参数
    import argparse

    parser = argparse.ArgumentParser(description="分布式文件同步系统 TUI 监控器")
    parser.add_argument(
        "--host", default="localhost", help="后端服务主机地址 (默认: localhost)"
    )
    parser.add_argument(
        "--port", type=int, default=8889, help="后端API端口 (默认: 8889)"
    )

    args = parser.parse_args()

    # 启动TUI
    tui = FileSyncTUI(args.host, args.port)
    tui.run()


if __name__ == "__main__":
    main()
